#!/usr/bin/env python3
# coding:utf-8
import sys
import getopt
import asyncio
import threading
import time
from loguru import logger

# ros2
import rclpy
from rclpy.node import Node

# local
from Charger_C3 import Charger_C3
from Charger_Ros import Charger_Ros

Default_Config = {
    "host": "0.0.0.0",
    "port": 9967,
    "model": "C3",
}


class ChargerService:
    """
    充电桩tcpServer服务
    """

    def __init__(self, config):
        self.config = config
        self.init_data()
        self.init_log()
        self.init_ros()

    def init_data(self):
        model = self.config["model"]
        if model == "C3":
            self.charger_impl = Charger_C3(self)
        else:
            raise ValueError(f"不支持的充电桩型号: {model}")

    def init_ros(self):
        rclpy.init(args=None)
        self.ros_node = Charger_Ros(self)
        self.task_ros = threading.Thread(target=self.loop_run_ros, daemon=True)
        self.task_ros.start()

    def loop_run_ros(self):
        rclpy.spin(self.ros_node)
        self.ros_node.destroy_node()
        rclpy.shutdown()

    def init_log(self):
        # 移除默认的处理器
        logger.remove()
        # 自定义日志格式
        log_format = (
            "<green>{time:HH:mm:ss.S}</green>| "
            "<level>{level: <8}</level>| "
            "<level>{message}</level>"
        )
        logger.add(sys.stderr, format=log_format, enqueue=True, colorize=True)

    async def loop_run(self):
        """启动异步 TCP 服务端"""
        host = self.config["host"]
        port = self.config["port"]
        # 创建异步服务器
        server = await asyncio.start_server(self.handle_client, host, port)
        self.event_loop = asyncio.get_running_loop()
        # 获取服务器地址
        addr = server.sockets[0].getsockname()
        print(f"充电服务器运行在 {addr}")

        # 启动服务器并等待其关闭
        async with server:
            await server.serve_forever()

    async def handle_client(
        self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter
    ) -> None:
        """处理客户端连接"""
        # 获取客户端地址
        client_addr = writer.get_extra_info("peername")
        print(f"新连接来自 {client_addr}")

        try:
            while True:
                # 读取客户端发送的数据 (最多 1024 字节)
                data = await reader.read(1024)
                if not data:  # 客户端关闭连接
                    break

                await self.charger_impl.handler_recv_msg(data, writer)

        except asyncio.CancelledError:
            print(f"客户端 {client_addr} 连接被取消")
        except Exception as e:
            print(f"处理客户端 {client_addr} 时发生错误: {e}")
        finally:
            # 删除客户端
            self.charger_impl.del_client(writer)
            # 关闭socket
            writer.close()
            await writer.wait_closed()
            print(f"客户端 {client_addr} 连接已关闭")

    async def send_data(self, writer, send_data):
        if writer is None:
            return
        writer.write(send_data)
        await writer.drain()

    def async_task_send_data(self, writer, send_data):
        if writer is None:
            return
        # 协程 跨线程发送数据
        writer.write(send_data)
        asyncio.run_coroutine_threadsafe(writer.drain(), self.event_loop)


def parse_args():
    global Default_Config
    config = Default_Config
    try:
        opts, args = getopt.getopt(sys.argv[1:], "p:m:", ["port=", "host=", "model="])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(err)  # will print something like "option -a not recognized"
        sys.exit(2)

    global Robot_ID
    for o, a in opts:
        if o in ("-p", "--port"):
            config["port"] = int(a)
        elif o in ("--host"):
            config["host"] = a
        if o in ("-m", "--model"):
            config["model"] = a
        else:
            assert False, "unhandled option"
    return config


def main():
    config = parse_args()
    charger_server = ChargerService(config)
    try:
        asyncio.run(charger_server.loop_run())
    except KeyboardInterrupt:
        print("服务器已关闭")


if __name__ == "__main__":
    main()
